package monarc.jscheduler.dag;

import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import java.util.Vector;

import monarc.MainSim;
import monarc.center.AbstractCPUUnit;
import monarc.center.Farm;
import monarc.jscheduler.dag.graph.Muchie;
import monarc.jscheduler.dag.graph.PMuchie;
import monarc.jscheduler.dag.graph.Nod;
import monarc.jscheduler.dag.graph.Procesor;
import monarc.jscheduler.dag.MonitorJob;
import monarc.util.Debugger;

import edu.uci.ics.jung.graph.impl.DirectedSparseGraph;
import edu.uci.ics.jung.graph.impl.UndirectedSparseGraph;

/**
 * 
 * @author Alexandra Olteanu
 *
 * System Status
 * 
 */
public class SystemStatus{

	public static final int CPUbound = 1;
	public static final int IObound = 2;
	public static final int CPUmixedIO = 3;
	public Vector<Double> CcrList;
	public int rt;
	public Farm currentFarm;
	public boolean homogeneous = false;
	public int heterogeneous_type = -1;
	public boolean same_cluster = false;
	public static final int ResCPUbound = 1;
	public static final int ResIObound = 2;
	public static final int ResCPUmixedIO = 3;
	
	
	public SystemStatus(Farm farm){
		CcrList = new Vector<Double>();
		currentFarm = farm;
	}
	
	public void calcNodeCCR(DirectedSparseGraph g){
		
		Set st = g.getVertices();
		Iterator iter = st.iterator();
		Nod a;
		int comm=0;
		
		while ( iter.hasNext() ){
			a = (Nod)iter.next();
			Set pred = a.getPredecessors();
			Iterator iter1 = pred.iterator();
			while( iter1.hasNext() )
			{	
				Nod nd = (Nod)iter1.next();
				Muchie mc = ( Muchie )nd.findEdge( a );
				comm+=mc.data;
			}
			double aux = 0;
			if(a.data!=0)
			   aux = comm/a.data;
			else 
				if (MainSim.useDebug) 
					Debugger.println( "Communication is not defined " );
			CcrList.add(aux);
		}	
	}
	
	public int calcCCR(DirectedSparseGraph g){
		
		Vector<Nod> NodeList = new Vector<Nod>();
		Vector<Muchie> EdgeList = new Vector<Muchie>();
		Set st = g.getVertices();
		Iterator iter = st.iterator();
		Nod a;
		double comp=0;
		double comm=0;
		double ccr;
		
		while ( iter.hasNext() ){
			a = (Nod)iter.next();
			NodeList.add(a);
			comp+=a.data;
			Set pred = a.getPredecessors();
			Iterator iter1 = pred.iterator();
			while( iter1.hasNext() )
			{	
				Nod nd = (Nod)iter1.next();
				Muchie mc = ( Muchie )nd.findEdge( a );
				EdgeList.add(mc);
				comm+=mc.data;
			}
		}
		System.out.println("Costurile sunt:"+comp+" - "+comm+"-"+comm/comp);
		ccr = comm/comp;
		if(ccr > 1*1.19)
			return IObound;
		else
			if(ccr < 1*0.89)
				return CPUbound;
			else 
				return CPUmixedIO;
	}
	
	public void detResourcesOmogenity(Farm farm){
		
			Vector CPU = farm.CPUs;
			double meanCPU = 0;
			double meanLink = 0;
			double meanMem = 0;
			double devCPU = 0;
			double devLink = 0;
			double devMem = 0;
			int nr = 0;
			
			for (int i=0; i<CPU.size(); i++) {
				AbstractCPUUnit cpu = (AbstractCPUUnit)CPU.get(i);
				meanCPU += cpu.totalCPU;
				meanLink += cpu.linkPort.maxSpeed; 
				meanMem += cpu.totalMemory;
				nr++;
			}
			
			meanCPU/=nr;
			meanLink/=nr;
			meanMem/=nr;
			
			System.out.println("Media: "+meanCPU +"-"+meanLink);
			for (int i=0; i<CPU.size(); i++) {
				AbstractCPUUnit cpu = (AbstractCPUUnit)CPU.get(i);
				devCPU += (cpu.totalCPU-meanCPU)*(cpu.totalCPU-meanCPU);
				devLink += (cpu.linkPort.maxSpeed - meanLink)*(cpu.linkPort.maxSpeed - meanLink);
				devMem += (cpu.totalMemory - meanMem)*(cpu.totalMemory - meanMem);
			}
			
			devCPU/=nr;
			devLink/=nr;
			devMem/=nr;
			
			devCPU = Math.sqrt(devCPU);
			devLink = Math.sqrt(devLink);
			devMem = Math.sqrt(devMem);
			System.out.println("deviatia standard: "+devCPU +"-"+devLink+"-"+devMem);
			
			if(devCPU < 10 && devMem < 50){
				this.homogeneous = true;
				this.heterogeneous_type = -1;
			}
			else{
				this.homogeneous = false;
				if(devCPU > 10 && devMem > 50)
					this.heterogeneous_type = 1; //complete
				else
					if(devCPU > 10)
						this.heterogeneous_type = 2; //same mem
					else
						this.heterogeneous_type = 3; //same cpu
			}
			
			if(devLink < 20)
				this.same_cluster = true;
			else
				this.same_cluster = false;
		 	
	}
	public void detProccesorsOmogenity(UndirectedSparseGraph procesoare){
		
		Set st = procesoare.getVertices();
		Iterator iter = st.iterator();
		Procesor a;
		double mean =0;
		double dev = 0;
		int nr = 0;
		
		while ( iter.hasNext() ){
			a = (Procesor)iter.next();
			mean+=a.data;
			nr++;
		}
		
		mean/=nr;
		iter = st.iterator();
		
		while ( iter.hasNext() ){
			a = (Procesor)iter.next();
			dev+=(a.data-mean)*(a.data-mean);
		}
		
		dev/=nr;
		dev = Math.sqrt(dev);
		System.out.println("deviatia standard: "+dev);
	}
	
	public int detResourcesType(Farm farm){
		Vector CPU = farm.CPUs;
		float comp=0;
		float comm=0;
		float resCcr;
		for (int i=0; i<CPU.size(); i++) {
			AbstractCPUUnit cpu = (AbstractCPUUnit)CPU.get(i);
			comm += cpu.linkPort.maxSpeed;
			comp += cpu.totalCPU;
		}
		System.out.println("Disponibilitate sunt:"+comp+" - "+comm +" - "+comm/comp);
		
		resCcr = comm/comp;
		if(resCcr > 1*1.19)
			return ResIObound;
		else
			if(resCcr < 1*0.89)
				return ResCPUbound;
			else 
				return ResCPUmixedIO;
	}
	
	public void detProccesorsType(UndirectedSparseGraph procesoare){
		
		Vector<Procesor> NodeList = new Vector<Procesor>();
		Vector<PMuchie> EdgeList = new Vector<PMuchie>();
		Set st = procesoare.getVertices();
		Iterator iter = st.iterator();
		Procesor a;
		
		float comp=0;
		float comm=0;
		
		while ( iter.hasNext() ){
			a = (Procesor)iter.next();
			NodeList.add(a);
			comp+=a.data;
			Set pred = a.getPredecessors();
			Iterator iter1 = pred.iterator();
			while( iter1.hasNext() )
			{	
				Procesor nd = (Procesor)iter1.next();
				PMuchie mc = ( PMuchie )nd.findEdge( a );
				EdgeList.add(mc);
				comm+=mc.data;
			}
		}
		System.out.println("Costurile sunt:"+comp+" - "+comm/2);
	}
	
	public void detGraphStructure(){
		//nothing here
	}
	
}